package cn.mysdp.biz.controller;

import cn.mysdp.biz.dto.request.BaseRequest;
import cn.mysdp.utils.JavaBeansUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PostMapping;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName:
 * @Description:
 * @Author: SDP
 * @Date: 2020-10-30
 * Table:
 * Comment:
 */
@Component
@Slf4j
public class BaseController {

    @Autowired
    HttpServletRequest httpServletRequest;

    public static final Map<String, Map<String, Class>> requestClassMap = new HashMap<>();
    public static final Map<String, Class> classMap = new HashMap<>();

    public static final Map<String, String> beanMap = new HashMap<>();

    public static final Map<String, Method> urlMap = new HashMap<>();

    public static void addRequestClass(String moduleName, String methodName, String beanName, Class clz, Class requestClz) {
        String key = moduleName + "/"+methodName;
        synchronized (BaseController.class) {
            if (!requestClassMap.containsKey(moduleName)) {
                requestClassMap.put(moduleName, new HashMap<>());
            }
            if (!requestClassMap.get(moduleName).containsKey(methodName)) {
                requestClassMap.get(moduleName).put(methodName, requestClz);
            }
            if (!classMap.containsKey(key)) {
                classMap.put(key, clz);
                beanMap.put(key, beanName);

                Method[] methods = clz.getDeclaredMethods();
                for(Method method: methods) {
                    if (method.isAnnotationPresent(PostMapping.class)) {
                        PostMapping postMapping = method.getAnnotation(PostMapping.class);
                        method.setAccessible(true);
                        for(String url: postMapping.value()) {
                            urlMap.put(moduleName + url, method);
                        }
                    }
                }
            }
        }
    }

    public void fixRequest(String module, String method, Object request) throws Exception {
        fixRequest(module, method, request, null);
    }

    public String localIp = null;

    public void fixRequest(String module, String method, Object requet, Integer callFrom) throws Exception {
        String ip = getIpAddr(httpServletRequest);
        if (!"0:0:0:0:0:0:0:1".equals(ip) && !"127.0.0.1".equals(ip)) {
            if (localIp == null) {
                localIp = InetAddress.getLocalHost().getHostAddress();
            }
            if (localIp == null || !localIp.equals(ip)) {
                throw new Exception("禁止远程访问："+ip);
            }
        }
    }

    public String getIpAddr(HttpServletRequest request) {

        String ip = request.getRemoteAddr();

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("x-forwarded-for");
        }

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("http_client_ip");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip != null && ip.indexOf(",") != -1) {
            ip = ip.substring(ip.lastIndexOf(",") + 1, ip.length()).trim();
        }
        return ip;
    }

    public void fixResult(String module, String method, Object request) throws Exception {
        if(request != null && request instanceof List) {
            List<Object> list = (List<Object>) request;
            for(Object obj:list) {
                Field f = JavaBeansUtil.getField(obj.getClass(), "extraMap");
                if(f != null) {
                    f.set(obj, null);
                }
            }
        }

    }

    public String toJSONString(Object request) {
        return JavaBeansUtil.toJSONString(request);
    }

    public JSONObject parseObject(String request) {
        return JavaBeansUtil.parseObject(request);
    }

    public void clearPageInfo(BaseRequest request) {
        if(request.getQueryOptions() != null) {
            request.getQueryOptions().remove("count");
            request.getQueryOptions().remove("limit");
        }
        request.setPageNo(null);
        request.setPageSize(null);
    }

    public String encrypt(BaseRequest request, String data) throws Exception {
        throw new Exception("not implement");
    }
    public Object decrypt(String moduleName, String methodName, String strRequest, Class clz) throws Exception {
        throw new Exception("not implement");
    }

    public String exportExcel(Object request,
                              Collection list) throws Exception {
        throw new Exception("not implement");
    }
}
